package git.soulbgm.hdfs.aspect;

import git.soulbgm.hdfs.annotation.HdfsOperate;
import git.soulbgm.hdfs.common.HdfsClient;
import git.soulbgm.hdfs.common.HdfsPool;
import git.soulbgm.hdfs.common.HdfsTool;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 自动归还对象池对象
 *
 * @author SoulBGM
 * @date 2022/06/29 10:47
 */
@Aspect
public class HdfsPoolAspect {

    private static final Logger log = LoggerFactory.getLogger(HdfsPoolAspect.class);

    /**
     * 对象池
     */
    private final HdfsPool hdfsPool;

    public HdfsPoolAspect(HdfsPool hdfsPool) {
        this.hdfsPool = hdfsPool;
    }

    /**
     * 作用于注解了{@link HdfsOperate @HdfsAnnotation}的方法
     */
    @Pointcut(value = "@annotation(git.soulbgm.hdfs.annotation.HdfsOperate)")
    public void hdfsPointcut() {
    }

    /**
     * 将获得对象池对象的操作锁定
     *
     * @return HdfsClient {@link HdfsClient}
     * @throws Exception 获得对象池对象的操作异常
     */
    private synchronized HdfsClient borrowObject() throws Exception {
        return hdfsPool.borrowObject();
    }

    /**
     * 切面操作，在{@link HdfsTool HdfsTool}注解了{@link HdfsOperate @HdfsAnnotation}的方法运
     * 行前注入{@link HdfsClient}对象，并且运行后自动归还对象到对象池
     *
     * @param jp ProceedingJoinPoint
     * @return -
     * @throws Throwable 执行HdfsTool方法或returnObject异常
     */
    @Around(value = "hdfsPointcut()")
    public Object aroundAdvice(ProceedingJoinPoint jp) throws Throwable {
        HdfsClient hdfsClient = borrowObject();
        try {
            HdfsTool.setHdfsClient(hdfsClient);
            Object o = jp.proceed();
            hdfsPool.returnObject(hdfsClient);
            return o;
        } catch (Throwable e) {
            log.error("执行HdfsTool方法或returnObject报错", e);
            throw e;
        } finally {
            HdfsTool.removeThreadLocal();
        }
    }
}

